package handler

import (
	"context"
	"fmt"
	"github.com/golang/protobuf/ptypes/empty"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"gorm.io/gorm"
	"project06_src/src/global"
	"project06_src/src/model"
	"project06_src/src/proto"
	"time"
)

func UserModel2UserInfoResponse(sub model.Subscribe) proto.SubInfo {
	return proto.SubInfo{
		Id:        int32(sub.ID),
		OwnerId:   int32(sub.UserId),
		Title:     sub.Title,
		Describe:  sub.Describe,
		Address:   sub.Address,
		Reward:    int32(sub.Reward),
		StartData: sub.StartDate.Format("2020-02-02"),
		EndData:   sub.EndDate.Format("2020-02-02"),
		Phone:     sub.Phone,
		Owner: &proto.UserInfoResponse{
			Id:       int32(sub.Onwer.ID),
			UserName: sub.Onwer.UserName,
			Password: sub.Onwer.Password,
			Phone:    sub.Onwer.Phone,
			Name:     sub.Onwer.Name,
			Identify: sub.Onwer.Identify,
			RoleID:   int32(sub.Onwer.RoleID),
		},
	}
}

func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {

		if page == 0 {
			page = 1
		}

		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}
		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

type SubscribeService struct {
}

func (s *SubscribeService) CreateSubscribe(ctx context.Context, sub *proto.SubInfo) (*proto.SubInfo, error) {
	startDate, err := time.Parse("2006-12-01", sub.StartData)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "时间转换失败")
	}
	endDate, err := time.Parse("2006-12-01", sub.EndData)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "时间转换失败")
	}
	mySub := model.Subscribe{
		UserId:    int(sub.OwnerId),
		Title:     sub.Title,
		Describe:  sub.Describe,
		StartDate: &startDate,
		EndDate:   &endDate,
		Reward:    int(sub.Reward),
		Address:   sub.Address,
		Phone:     sub.Phone,
	}
	res := global.Db.Create(&mySub)
	if res.Error != nil {
		return nil, status.Errorf(codes.Internal, "内部错误，创建失败")
	}
	result := UserModel2UserInfoResponse(mySub)
	return &result, nil
}

func (s *SubscribeService) GetSubList(ctx context.Context, req *proto.PageInfo) (*proto.SubResponse, error) {
	var subscribes []model.Subscribe
	var subRes proto.SubResponse
	result := global.Db.Model(&model.Subscribe{}).Preload("Onwer").Scopes(Paginate(int(req.Pn), int(req.Psize))).Joins("join user on user.id = subscribe.user_id").Find(&subscribes)
	if result.Error == gorm.ErrRecordNotFound {
		return nil, status.Errorf(codes.Internal, "未找到")
	}
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, "内部错误")
	}

	for _, v := range subscribes {
		subInfo := UserModel2UserInfoResponse(v)
		subRes.SubInfo = append(subRes.SubInfo, &subInfo)
	}

	return &subRes, nil

}

func (s *SubscribeService) GetSubById(ctx context.Context, req *proto.SubIdRequest) (*proto.SubInfo, error) {
	var sub model.Subscribe
	res := global.Db.Joins("join user on user.id = subscribe.user_id").Where("subscribe.id = ?", req.SubId).First(&sub)
	if res.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "订单不存在")
	}
	if res.Error != nil {
		return nil, res.Error
	}

	result := UserModel2UserInfoResponse(sub)
	return &result, nil
}

func (s *SubscribeService) GetSubBySubName(ctx context.Context, req *proto.SubNameRequest) (*proto.SubResponse, error) {
	var subscribes []model.Subscribe
	var subRes proto.SubResponse
	result := global.Db.Joins("join user on user.id = subscribe.user_id").Where("subscribe.title like ?", fmt.Sprintf("%", req.Title, "%")).Find(&subscribes)
	if result.Error == gorm.ErrRecordNotFound {
		return nil, status.Errorf(codes.Internal, "未找到")
	}
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, "内部错误")
	}

	for _, v := range subscribes {
		subInfo := UserModel2UserInfoResponse(v)
		subRes.SubInfo = append(subRes.SubInfo, &subInfo)
	}

	return &subRes, nil

}

func (s *SubscribeService) UpdateSub(ctx context.Context, req *proto.UpdateSubRequest) (*emptypb.Empty, error) {
	var sub model.Subscribe
	res := global.Db.Where("subscribe.id = ?", req.SubId).First(&sub)
	if res.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}

	sub.Title = req.Title
	myEndTime, _ := time.Parse("2006-02-01", req.EndData)
	sub.EndDate = &myEndTime
	myStartTime, _ := time.Parse("2006-02-02", req.StartData)
	sub.StartDate = &myStartTime
	sub.Phone = req.Phone
	sub.Describe = req.Describe
	sub.Address = req.Address
	sub.Reward = int(req.Reward)

	result := global.Db.Save(&sub)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, "修改失败")
	}
	return &empty.Empty{}, nil
}

func (s *SubscribeService) DeleteSub(ctx context.Context, req *proto.DeleteSubRequest) (*emptypb.Empty, error) {
	var sub model.Subscribe
	res := global.Db.Where("subscribe.id = ?", req.SubId).First(&sub)
	if res.Error == gorm.ErrRecordNotFound {
		return nil, status.Errorf(codes.NotFound, "订单不存在")
	}

	if result := global.Db.Where("subscribe.id = ? and subscribe.user_id = ?", req.SubId, req.UserId).Delete(&sub); result.Error != nil {
		return nil, status.Errorf(codes.Internal, "内部错误")
	}
	return &empty.Empty{}, nil
}

func (s *SubscribeService) GetSubByUserId(ctx context.Context, req *proto.UserIdRequest) (*proto.SubResponse, error) {
	var sub []model.Subscribe
	var subRes proto.SubResponse
	res := global.Db.Model(&model.Subscribe{}).Preload("Onwer").Joins("join user on user.id = subscribe.user_id").Where("subscribe.user_id = ?", req.UserId).Find(&sub)
	if res.Error == gorm.ErrRecordNotFound {
		return nil, status.Errorf(codes.NotFound, "该用户未提交订单")
	}
	if res.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户未提交任何订单")
	}
	if res.Error != nil {
		return nil, status.Errorf(codes.Internal, "内部错误")
	}

	for _, v := range sub {
		subInfo := UserModel2UserInfoResponse(v)
		subRes.SubInfo = append(subRes.SubInfo, &subInfo)
	}

	return &subRes, nil
}
